<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // promise基本规则
        // 1.首先Promise构造函数会立即执行,而Promise.then()内部的代码在当次事件循环的结尾立即执行（微任务）
        // 2.Promise的状态一旦由等待pending变为成功fulfilled或者失败reject。
        // 那么当前Promise被标记为完成,后面则不会再次改变该状态.
        // 3.resolve函数和reject函数都将当前Promise状态改为完成,后面则不会再次改变该状态.
        // 4.Promise.resolve(value)
        // 返回一个状态由给定 value 决定的 Promise 对象。
        // 如果该值是 thenable(即，带有 then 方法的对象)，返回的 Promise 对象的最终状态由 then 方法执行决定；
        // 否则的话(该 value 为空，基本类型或者不带 then 方法的对象),返回的 Promise 对象状态为 fulfilled，
        // 并且将该 value 传递给对应的 then 方法。通常而言，如果你不知道一个值是否是 Promise 对象，
        // 使用 Promise.resolve(value) 来返回一个 Promise 对象,这样就能将该 value 以 Promise 对象形式使用。
        // 5. Promise.all(iterable)/Promise.race(iterable)
        // 简单理解，这2个函数，是将接收到的promise列表的结果返回，区别是，all是等待所有的promise都触发成功了，才会返回，
        // 而arce有一个成功了就会返回结果。其中任何一个promise执行失败了，都会直接返回失败的结果。
        // 6.Promise对象的构造函数只会调用一次，then方法和catch方法都能多次调用，但一旦有了确定的结果，再次调用就会直接返回结果。








        // 题目一
        // const promise = new Promise((resolve, reject) => {
        //     console.log(1);
        //     resolve();
        //     console.log(2);
        //     reject('error');
        // })
        // promise.then(() => {
        //     console.log(3);
        // }).catch(e => console.log(e))
        // console.log(4);


        // 题目二
        // const promise = new Promise((resolve, reject) => {
        //     setTimeout(() => {
        //         console.log('once');
        //         resolve('success');
        //     }, 1000)
        // })
        // promise.then((res) => {
        //     console.log(res);
        // })
        // promise.then((res) => {
        //     console.log(res);
        // })


        // 题目三
        // Promise.resolve(1).then(2).then(Promise.resolve(3)).then(console.log)
        // Promise.resolve(1)会返回一个Promise对象并将1当作then的参数.
        // 而then或者catch的参数期望是函数,传入非函数则会发生值穿透.


        // 题目四
        // 顺序加载10张图片,图片地址已知,但是同时最多加载三张,用Promise实现
        // const baseUrl = 'http://img.aizhifou.cn/';
        // const urls = ['1.png', '2.png', '3.png', '4.png', '5.png', '6.png', '7.png', '8.png', '9.png', '10.png'];
        // const loadImg = function(url, i) {
        //     return new Promise((resolve, reject) => {
        //         try {
        //             // 加载一张图片
        //             let image = new Image();
        //             image.onload = function() {
        //                 resolve(i)
        //             }
        //             image.onerror = function() {
        //                 reject(i)
        //             };
        //             image.src = baseUrl + url;
        //         } catch (e) {
        //             reject(i)
        //         }
        //     })
        // }

        // function startLoadImage(urls, limits, endHandle) {
        //     // 当前存在的promise队列
        //     let promiseMap = {};
        //     // 当前索引对应的加载状态，无论成功，失败都会标记为true，格式： {0: true, 1: true, 2: true...}
        //     let loadIndexMap = {};
        //     // 当前以及加载到的索引，方便找到下一个未加载的索引，为了节省性能，其实可以不要
        //     let loadIndex = 0;
        //     const loadAImage = function() {
        //         // 所有的资源都进入了异步队列
        //         if (Object.keys(loadIndexMap).length === urls.length) {
        //             // 所有的资源都加载完毕，或者进入加载状态，递归结束
        //             const promiseList = Object.keys(promiseMap).reduce((arr, item) => {
        //                 arr.push(promiseMap[item]);
        //                 return arr
        //             }, [])
        //             Promise.all(promiseList).then(res => {
        //                 // 这里如果没有加载失败，就会在所有加载完毕后执行，如果其中某个错误了，这里的结果就不准确，不过这个不是题目要求的。
        //                 console.log('all');
        //                 endHandle && endHandle()
        //             }).catch((e) => {
        //                 console.log('end:' + e);
        //             })
        //         } else {
        //             // 遍历，知道里面有3个promise
        //             while (Object.keys(promiseMap).length < limits) {
        //                 for (let i = loadIndex; i < urls.length; i++) {
        //                     if (loadIndexMap[i] === undefined) {
        //                         loadIndexMap[i] = false;
        //                         promiseMap[i] = loadImg(urls[i], i);
        //                         loadIndex = i;
        //                         break;
        //                     }
        //                 }
        //             }
        //             // 获取当前正在进行的promise列表，利用reduce从promiseMap里面获取
        //             const promiseList = Object.keys(promiseMap).reduce((arr, item) => {
        //                 arr.push(promiseMap[item]);
        //                 return arr
        //             }, [])
        //             Promise.race(promiseList).then((index) => {
        //                 // 其中一张加载成功，删除当前promise，让PromiseList小于limit，开始递归，加载下一张
        //                 console.log('end:' + index);
        //                 loadIndexMap[index] = true;
        //                 delete promiseMap[index];
        //                 loadAImage();
        //             }).catch(e => {
        //                 // 加载失败也继续
        //                 console.log('end：' + e);
        //                 loadIndexMap[e] = true;
        //                 delete promiseMap[e];
        //                 loadAImage();
        //             })
        //         }
        //     }
        //     loadAImage()
        // }
        // startLoadImage(urls, 3)




        // 题目五
        // const p1 = () => (new Promise((resolve, reject) => {
        //     console.log(1);
        //     let p2 = new Promise((resolve, reject) => {
        //         console.log(2);
        //         const timeOut1 = setTimeout(() => {
        //             console.log(3);
        //             resolve(4);
        //         }, 0)
        //         resolve(5);
        //     })
        //     resolve(6);
        //     p2.then((arg) => {
        //         console.log(arg);
        //     })
        // }));

        // const timeOut2 = setTimeout(() => {
        //     console.log(8);
        //     const p3 = new Promise(reject => {
        //         reject(9);
        //     }).then(res => {
        //         console.log(res);
        //     })
        // }, 0)

        // p1().then((arg) => {
        //     console.log(arg);
        // })
        // console.log(10);
    </script>
</body>

</html>